"""
传感器数据处理模块
Sensor data handling module
"""

import serial
import time
import logging
from datetime import datetime
from modules.gps_handler import GPSHandler
from config import SERIAL_CONFIG, SENSOR_CONFIG

# 兼容新版本pymodbus的导入方式
try:
    from pymodbus.client import ModbusSerialClient
    PYMODBUS_AVAILABLE = True
except ImportError:
    try:
        from pymodbus.client.sync import ModbusSerialClient
        PYMODBUS_AVAILABLE = True
    except ImportError:
        PYMODBUS_AVAILABLE = False
        logging.warning("pymodbus未安装，无法使用Modbus功能")

if PYMODBUS_AVAILABLE:
    from pymodbus.exceptions import ModbusException

logger = logging.getLogger(__name__)

class SensorHandler:
    def __init__(self, sensor_type=None):
        """
        初始化传感器处理器
        sensor_type: 'serial' 或 'modbus'，如果为None则从配置文件读取
        """
        self.sensor_type = sensor_type or SENSOR_CONFIG.get('type', 'serial')
        self.port = SERIAL_CONFIG['sensor_port']
        self.baudrate = SERIAL_CONFIG['sensor_baudrate']
        self.timeout = SERIAL_CONFIG['timeout']
        self.gps_handler = GPSHandler()
        self.measurement_environment = None
        
        # Modbus相关初始化
        if self.sensor_type == 'modbus':
            if not PYMODBUS_AVAILABLE:
                raise ImportError("使用Modbus功能需要安装pymodbus: pip install pymodbus")
            
            self.device_addr = SENSOR_CONFIG.get('modbus_device_addr', 1)
            self.reading_interval = SENSOR_CONFIG.get('reading_interval', 5)
            self.max_retry_attempts = SENSOR_CONFIG.get('max_retry_attempts', 3)
            self.modbus_client = None
            self._init_modbus_client()
        
    def _init_modbus_client(self):
        """初始化Modbus客户端"""
        try:
            self.modbus_client = ModbusSerialClient(
                port=self.port,
                baudrate=self.baudrate,
                timeout=self.timeout,
                parity='N',
                stopbits=1,
                bytesize=8
            )
        except TypeError:
            # 兼容旧版本
            self.modbus_client = ModbusSerialClient(
                method='rtu',
                port=self.port,
                baudrate=self.baudrate,
                timeout=self.timeout,
                parity='N',
                stopbits=1,
                bytesize=8
            )
        
    def get_measurement_environment(self):
        """获取测量环境信息"""
        if self.measurement_environment is None:
            print("\n=== 测量环境设置 ===")
            print("请输入当前的测量环境信息：")
            print("例如：室内、室外、办公室、实验室、工厂、农田等")
            
            while True:
                env_input = input("测量环境: ").strip()
                if env_input:
                    self.measurement_environment = env_input
                    print(f"测量环境已设置为: {self.measurement_environment}")
                    break
                else:
                    print("请输入有效的环境信息")
        
        return self.measurement_environment
    
    def read_modbus_sensors(self):
        """读取Modbus传感器数据"""
        if not PYMODBUS_AVAILABLE:
            logger.error("pymodbus未安装，无法读取Modbus传感器")
            return None
            
        retry_count = 0
        while retry_count < self.max_retry_attempts:
            try:
                if not self.modbus_client.connect():
                    logger.error(f"Modbus设备连接失败 (尝试 {retry_count + 1}/{self.max_retry_attempts})")
                    retry_count += 1
                    time.sleep(1)
                    continue
                    
                # 读取温湿度
                try:
                    temp_hum_result = self.modbus_client.read_holding_registers(
                        address=0x0000, count=2, slave=self.device_addr
                    )
                except TypeError:
                    temp_hum_result = self.modbus_client.read_holding_registers(
                        address=0x0000, count=2, unit=self.device_addr
                    )
                
                # 读取气压
                try:
                    pressure_result = self.modbus_client.read_holding_registers(
                        address=0x0010, count=1, slave=self.device_addr
                    )
                except TypeError:
                    pressure_result = self.modbus_client.read_holding_registers(
                        address=0x0010, count=1, unit=self.device_addr
                    )
                
                if not temp_hum_result.isError() and not pressure_result.isError():
                    data = {
                        "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        "measurement_environment": self.get_measurement_environment(),
                        "temperature": temp_hum_result.registers[1] / 10.0,
                        "humidity": temp_hum_result.registers[0] / 10.0,
                        "pressure": pressure_result.registers[0] / 100.0
                    }
                    
                    # 获取位置信息
                    logger.info("正在获取GPS位置信息...")
                    location_info = self.gps_handler.get_location_info()
                    data["location"] = location_info
                    
                    return data
                else:
                    logger.error(f"Modbus传感器读取失败 (尝试 {retry_count + 1}/{self.max_retry_attempts})")
                    retry_count += 1
                    time.sleep(1)
                    
            except ModbusException as e:
                logger.error(f"Modbus通信错误 (尝试 {retry_count + 1}/{self.max_retry_attempts}): {e}")
                retry_count += 1
                time.sleep(1)
            except Exception as e:
                logger.error(f"Modbus传感器读取异常 (尝试 {retry_count + 1}/{self.max_retry_attempts}): {e}")
                retry_count += 1
                time.sleep(1)
            finally:
                if self.modbus_client:
                    self.modbus_client.close()
        
        logger.error(f"Modbus传感器读取失败，已重试{self.max_retry_attempts}次")
        return None
    
    def parse_sensor_data(self, raw_data):
        """解析传感器数据（原有串口方式）"""
        # 只处理包含温度或湿度的数据
        if "Temperature" not in raw_data and "Humidity" not in raw_data:
            return None
        
        # 创建数据记录
        data = {
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "measurement_environment": self.get_measurement_environment()
        }
        
        try:
            # 提取温度
            if "Temperature" in raw_data:
                temp_str = raw_data.split("Temperature:")[1].split(",")[0].strip()
                data["temperature"] = float(temp_str.replace("C", ""))
            
            # 提取湿度
            if "Humidity" in raw_data:
                humid_str = raw_data.split("Humidity:")[1].split(",")[0].strip()
                data["humidity"] = float(humid_str.replace("%", ""))
            
            # 获取位置信息
            logger.info("正在获取GPS位置信息...")
            location_info = self.gps_handler.get_location_info()
            data["location"] = location_info
            
            return data
        except (ValueError, IndexError) as e:
            logger.error(f"传感器数据解析错误: {e}")
            return None
    
    def connect_sensor(self):
        """连接传感器"""
        if self.sensor_type == 'modbus':
            return self._connect_modbus_sensor()
        else:
            return self._connect_serial_sensor()
    
    def _connect_serial_sensor(self):
        """连接串口传感器（原有方式）"""
        try:
            ser = serial.Serial(self.port, self.baudrate, timeout=self.timeout)
            logger.info(f"串口传感器连接成功: {self.port}")
            return ser
        except Exception as e:
            logger.error(f"串口传感器连接失败: {e}")
            raise
    
    def _connect_modbus_sensor(self):
        """连接Modbus传感器"""
        if not PYMODBUS_AVAILABLE:
            raise ImportError("使用Modbus功能需要安装pymodbus: pip install pymodbus")
            
        try:
            if self.modbus_client.connect():
                logger.info(f"Modbus传感器连接成功: {self.port}")
                self.modbus_client.close()  # 连接测试后关闭，实际读取时再连接
                return True
            else:
                raise Exception("Modbus连接失败")
        except Exception as e:
            logger.error(f"Modbus传感器连接失败: {e}")
            raise
